/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物体.h"
#include "物体/S_物体.h"
#include "S_摄像机.h"



#include <core/引擎配置.h>
#include "core/属性.h"
#include "core/动画/an_曲线.h"

#include "面/intern/网格.h"
#include "面/面.h"
#include "面/几何模型生成.h"

#include "intern/模型/S_模型.h"
#include "intern/粒子系统.h"
#include "intern/expand/FBX模型加载保存.h"
#include "intern/expand/OBJ模型加载保存.h"
#include "intern/expand/STL模型加载保存.h"
#include "intern/灯光.h"



#include <file_载入保存数据.h>
#include <file_文件名数据.h>
#include <matXX.h>
#include <几何图形/图形相交.h>
#include <随机数.h>


#include "材质/预设材质.h"
#include "材质/材质.h"



static std::map<std::wstring, S_物体*> g物体表;

static void f_ob_分配变换矩阵(S_物体* ob, S_设备环境& ctx) {
	switch (ob->m_Type) {
	case E_物体类型::t_多边形:
	case E_物体类型::t_网格物体:
	case E_物体类型::t_灯光:
	case E_物体类型::t_包:
	case E_物体类型::t_线:
	case E_物体类型::t_线段:
	case E_物体类型::t_骨架:
	case E_物体类型::t_物体包: {
		f_ob_创建矩阵(ob);
		break;
	}
	default:
		break;
	}
}

Inline uint32 f_物体视口全局显示模式矫正(E_物体类型 物体类型, uint32 视口显示模式) {
	switch (物体类型)
	{
		case E_物体类型::t_多边形:
		case E_物体类型::t_微多边形:
		case E_物体类型::t_网格物体:
			return (视口显示模式 & 0x0000ffff) | (((视口显示模式 >> 16) & 0x000000ff) << 16);
		default:
			break;
	}
	return 视口显示模式;
	return (视口显示模式 & 0x0000ffff) | (视口显示模式 >> 16 &
		(E_物体视口显示::e_OVS_面
			| E_物体视口显示::e_OVS_边
			| E_物体视口显示::e_OVS_点
			| E_物体视口显示::e_OVS_预览
			| E_物体视口显示::e_OVS_渲染));
}


S_物体* f_ob_创建(E_物体类型 type, S_物体* froObj, S_设备环境 ctx) {
	S_物体* ob = 0;
	switch (ctx.m_Type) {
	case E_Vulkan: {
			switch (type) {
				case E_物体类型::t_网格物体: {
					ob = f_ob_创建(ctx, E_物体类型::t_网格物体);
					ob->f_setDataNum(1);
					ob->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan));
					//========================= 创建和初始化物体矩阵数据 ===========================
					f_ob_创建矩阵(ob);
					break;
				}

				case E_物体类型::t_多边形: {
					ob = f_ob_创建(ctx, E_物体类型::t_多边形);
					
					ob->m_UserData = f_surface_copy((S_多边形*)froObj->m_UserData);
					//ob->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN));
					//========================= 创建和初始化物体矩阵数据 ===========================
					f_ob_创建矩阵(ob);
					break;
				}
				
				case E_物体类型::t_摄像机: {
					auto* 像机 = f_ob_创建摄像机(ctx);
					//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
					ob = 像机;
					break;
				}
				
				//case E_物体类型::t_粒子: {
				//	auto p = new S_粒子系统(froObj);
				//	p->m_粒子 = f_create粒子系统(100, ctx);
				//	ob = p;
				//	break;
				//}
				case E_物体类型::t_粒子系统: {
					ob = new S_粒子系统(ctx);
					break;
				}
				
				case E_物体类型::t_骨骼: {
					ob = f_ob_创建骨骼(froObj, ctx);
					break;
				}
				case E_物体类型::t_骨架: {
					ob = new S_物体(type);
					if (froObj) {
						if (froObj->m_变换矩阵.m_Mem.m_数量) {
							f_ob_创建矩阵(ob);
						}
						//f_ob_创建矩阵(ob, ctx);
					}
					break;
				}
				case E_物体类型::t_物体包: {
					ob = new S_物体(type);
					if (froObj) {
						//f_ob_创建矩阵(ob, ctx);
						if (froObj->m_变换矩阵.m_Mem.m_数量) {
							f_ob_创建矩阵(ob);
						}
					}
					break;
				}

				case E_物体类型::t_空: {
					ob = new S_物体(E_物体类型::t_空);
					S_GL立即模式;
				}
				break;

				case E_物体类型::t_虚拟体: {
					ob = new S_物体(E_物体类型::t_虚拟体);
					break;
				}
				
				case E_物体类型::t_实例: {
					ob = f_ob_创建实例(froObj, 0);
				}
				break;

			default:
				break;
			}
			if (froObj) {
				f_ob_set数据槽数量(ob, froObj->m_DataNum);
			}
			
		}
		break;
	case E_CUDA:
		switch (type)
		{
			case E_物体类型::t_网格物体: {
				auto* 模型 = new S_模型();
				模型->m_网格 = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_CUDA);
				ob = 模型;
			}
			break;

			case E_物体类型::t_摄像机: {
				auto* 像机 = new S_摄像机(ctx);
				//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
				ob = 像机;
			}
			break;

			case E_物体类型::t_灯光: {
				auto* 灯光 = new S_物体(E_物体类型::t_灯光);
				//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
				ob = 灯光;
			}
			break;

			//case E_物体类型::t_粒子: {
			//	auto p = new S_粒子系统(froObj);
			//	p->m_粒子 = f_create粒子系统(100, ctx);
			//	ob = p;
			//}
			break;

		default:
			break;
		}
		break;
	case E_DirectX12:
		ob = new S_物体(type);
		break;
	default:
		break;
	}

	return ob;
}

S_物体* f_ob_创建(S_设备环境& ctx, E_物体类型 type) {
	S_物体* ob = nullptr;
	switch (type) {
		case E_物体类型::t_摄像机: {
			ob = f_ob_创建摄像机(ctx);
			break;
		}
		case E_物体类型::t_粒子系统: {
			ob = new S_粒子系统(ctx);
			f_ob_创建矩阵(ob);
			break;
		}
	}
	if (ob) return ob;


	ob = new S_物体(type);
	ob->m_Ctx = ctx;

	switch (type) {
		case E_物体类型::t_实例:
			ob->m_是否实例 = true;
			break;
		
		case E_物体类型::t_骨骼:
			f_ob_创建矩阵(ob);
			f_ob_创建骨骼(ob);
			break;

		case E_物体类型::t_骨架: {
			S_骨架* 骨架 = f_ob_创建骨架();
			骨架->m_骨头物体 = ob;
			ob->m_UserData = 骨架;
		}
		case E_物体类型::t_骨节:

		case E_物体类型::t_虚拟体:
		
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_平行光:
		case E_物体类型::t_点光源:
		case E_物体类型::t_区域光:
		case E_物体类型::t_标注:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体:
		case E_物体类型::t_灯光:
		case E_物体类型::t_线:
		case E_物体类型::t_线段:
		case E_物体类型::t_包:
		case E_物体类型::t_点:
		case E_物体类型::t_空间曲线:
		case E_物体类型::t_粒子系统:
		case E_物体类型::t_物体包: {
			f_ob_创建矩阵(ob);
			break;
		}
		
		
		case E_物体类型::t_区域光_方形:
		case E_物体类型::t_区域光_圆形: {
			//ob->m_是否实例 = true;
			break;
		}
		break;
	}

	switch (type) {
		case E_物体类型::t_多边形: {
			ob->m_多边形 = new S_多边形;
		}
	}
	
	return ob;
}

S_物体* f_ob_创建(E_物体类型 type) {
	S_物体* ob = new S_物体(type);

	switch (type) {
		case E_物体类型::t_骨架:
			ob->m_UserData = f_ob_创建骨架();
		
		case E_物体类型::t_骨节:

		case E_物体类型::t_虚拟体:
		case E_物体类型::t_区域光:
		case E_物体类型::t_标注:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体:
		case E_物体类型::t_灯光:
		case E_物体类型::t_线:
		case E_物体类型::t_线段:
		case E_物体类型::t_包:
		case E_物体类型::t_物体包: {
			f_ob_创建矩阵(ob);
		}
	}
	return ob;
}

S_物体* f_ob_创建实例(S_物体* 父物体, uint32 loc) {
	//S_物体* ob = new S_物体(froObj->m_Type);
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;
	ob->m_父对象 = 父物体;
	return ob;
}

void f_ob_setName(S_物体* ob, const std::u16string& name) {
	ob->m_Name = name;
}

S_物体* f_ob_添加实例(S_物体* 父物体, uint32 实例ID) {
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;

	if (实例ID == -1) {
		ob->m_实例ID = 父物体->m_子物体.size();
	}
	else {
		ob->m_实例ID = 实例ID;
	}

	f_ob_添加矩阵(父物体, ob->m_实例ID);
	父物体->m_子物体.push_back(ob);
	return ob;
}

//S_物体* f_ob_创建骨骼(S_设备环境& ctx) {
//	S_物体* ob = new S_物体(E_物体类型::t_骨骼);
//	f_ob_创建矩阵(ob, ctx);
//	return ob;
//}



static void f_灯光变换更新(S_物体* ob, Mat44f* 矩阵, const Mat44f* 父级变换) {
	on_物体变换生成(ob, 矩阵, 父级变换);

	//Mat44f mat = f_mat44_构建XYZ变换矩阵({ ob->m_变换.location, ob->m_变换.rotation, {1,1,1} });
	//(*矩阵) = (*父级变换) * mat;


	auto* lp = f_ob_getLigth(ob);
	S_LightArea& light = f_bm_at<S_LightArea>(lp->m_灯光数据, 0);

	auto rot = f_mat44_to_33(*矩阵);
	light.m_pos = (*矩阵) * vec3{ 0,0,0 };
	light.m_dir = normalize(rot * vec3{ 0, 0, -1 });

	//ob->m_isUpdate = true;
}

S_物体* f_ob_创建灯光(S_设备环境& ctx, E_物体类型 type) {
	S_物体* ob = new S_物体(type);

	S_灯光场景数据* 灯光场景数据 = f_light_calloc灯光场景数据(ctx);

	灯光场景数据->m_灯光类型 = type;

	switch (type) {
		case E_物体类型::t_平行光: {
			//data = f_ob_calloc平行光();
			灯光场景数据->m_灯光数据 = f_bm_alloc(f_buf_getGlobal().m_平行光缓冲区, 1);
			break;
		}
		case E_物体类型::t_聚光灯: {
			//data = f_ob_calloc聚光灯();
			break;
		}
		case E_物体类型::t_点光源: {
			//data = f_ob_calloc点光源();
			break;
		}
		case E_物体类型::t_区域光: {
			//data = f_ob_calloc区域光();
			灯光场景数据->m_灯光数据 = f_bm_alloc(f_buf_getGlobal().m_区域光缓冲区, 1);
			f_ligth_init_区域光(f_bm_at<S_LightArea>(灯光场景数据->m_灯光数据));
			break;
		}
		
		default:
			return nullptr;
	}
	灯光场景数据->m_灯光类型 = type;
	灯光场景数据->m_灯光 = ob;
	
	f_ob_set数据槽数量(ob, 1);
	f_ob_set数据(ob, 灯光场景数据, 0);
	f_ob_创建矩阵(ob);

	ob->mf_变换回调更新 = f_灯光变换更新;
	
	return ob;
}

void f_ob_销毁(S_物体* ob) {
	switch (ob->m_Type) {

		case E_物体类型::t_多边形: {
			if (ob->m_UserData) {
				f_surface_销毁多边形((S_多边形*)ob->m_UserData);
			}
		}
		case E_物体类型::t_网格物体:
			//g更新变换物体.erase(ob);

		case E_物体类型::t_虚拟体: {
			for (uint32 i = 0; i < ob->m_DataNum; ++i) {
				f_surface_销毁网格(f_ob_getMesh(ob, i));
			}
			break;
		}

		case E_物体类型::t_骨骼: {
			auto* 骨骼 = f_ob_from骨骼(ob);
			auto* 骨节 = f_ob_from骨节(骨骼);

			free(骨骼);
			free(骨节);
		}

		case E_物体类型::t_平行光:
		case E_物体类型::t_点光源:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光: {
			auto light = f_ob_getLigth(ob);
			f_light_free灯光场景数据(light);
			break;
		}
	}

	delete ob;
}


void f_ob_改变物体类型(S_物体* ob, E_物体类型 新类型) {
	switch (ob->m_Type) {
		case E_物体类型::t_网格物体: {
			switch (新类型) {
				case E_物体类型::t_实例:
					ob->m_是否实例 = true;
					ob->f_setDataNum(0);
					break;

				case E_物体类型::t_网格物体: {
					if (ob->m_变换矩阵.m_Buf && !ob->m_变换矩阵.m_Mem.m_数量) {
						f_ob_添加矩阵(ob);
					}
					else {
						f_ob_创建矩阵(ob);
					}
					break;
				}

				case E_物体类型::t_多边形: {
					S_多边形* ply = (S_多边形*)ob->m_UserData;

					if (ply) {
						f_surface_销毁多边形(ply);
						ob->m_UserData = nullptr;

						if (ob->m_DataNum == 4) {
							f_surface_销毁网格(f_ob_getMesh(ob, 3));
							f_ob_set数据槽数量(ob, 3);
						}
					}
					break;
				}
			}
			break;
		}

		case E_物体类型::t_实例: {
			switch (新类型) {
				case E_物体类型::t_网格物体: {
					if (ob->m_变换矩阵.m_Buf) {
						f_ob_添加矩阵(ob);
					}
					else {
						f_ob_创建矩阵(ob);
					}
					ob->m_是否实例 = false;
					break;
				}
			
				case E_物体类型::t_多边形: {
				
					break;
				}
			}
			break;
		}

		case E_物体类型::t_多边形: {
			if (ob->m_变换矩阵.m_Buf && !ob->m_变换矩阵.m_Mem.m_数量) {
				f_ob_添加矩阵(ob);
			}
			else {
				f_ob_创建矩阵(ob);
			}
			if (!ob->m_UserData) {
				ob->m_UserData = f_surface_创建多边形();
			}
			break;
		}

		case E_物体类型::t_摄像机: {
			break;
		}

		case E_物体类型::t_粒子: {
			break;
		}
	
		case E_物体类型::t_骨骼: {
			break;
		}

		case E_物体类型::t_骨架: {
			break;
		}

		case E_物体类型::t_物体包: {
			break;
		}

		case E_物体类型::t_GL立即模式: {
			break;
		}

		case E_物体类型::t_空: {
			break;
		}

		default:
			break;
	}

	ob->m_Type = 新类型;

}






S_物体* f_创建BOX物体(const vec3& size, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建(E_物体类型::t_网格物体, 0, ctx);
	auto* mesh = f_ob_getMesh(obj, E_物体网格元素类型::e_MT_面);

	vec3 hafl = size / 2;

	std::vector<vec3> p(8);
	p[0] = { -hafl.x, -hafl.y, -hafl.z };
	p[1] = { -hafl.x, hafl.y, -hafl.z };
	p[2] = { hafl.x, hafl.y, -hafl.z };
	p[3] = { hafl.x, -hafl.y, -hafl.z };

	p[4] = { -hafl.x, -hafl.y, hafl.z };
	p[5] = { -hafl.x, hafl.y, hafl.z };
	p[6] = { hafl.x, hafl.y, hafl.z };
	p[7] = { hafl.x, -hafl.y, hafl.z };

	
	std::vector<uint32> index(36);
	if (三角化) {
		index[0] = 0; index[1] = 1; index[2] = 2;
		index[3] = 3; index[4] = 1; index[5] = 2;

		index[6] = 3; index[7] = 2; index[8] = 6;
		index[9] = 3; index[10] = 6; index[11] = 7;

		index[12] = 2; index[13] = 1; index[14] = 5;
		index[15] = 2; index[16] = 5; index[17] = 6;

		index[18] = 1; index[19] = 0; index[20] = 5;
		index[21] = 5; index[22] = 0; index[23] = 4;

		index[24] = 0; index[25] = 3; index[26] = 7;
		index[27] = 3; index[28] = 7; index[29] = 4;

		index[30] = 5; index[31] = 4; index[32] = 6;
		index[33] = 4; index[34] = 7; index[35] = 6;
	}
	
	mesh->f_fill顶点(p.data(), p.size());
	mesh->f_fill法线(p);
	f_me_fill索引(mesh, index);

	return obj;
}

S_物体* f_创建圆柱物体(const vec3& 高_半径, uint32 细分, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建(E_物体类型::t_网格物体, 0, ctx);
	auto* mesh = f_ob_getMesh(obj, E_物体网格元素类型::e_MT_面);

	std::vector<vec3> p(细分*2);
	f_构建圆柱(高_半径.x, { 高_半径.y, 高_半径.z }, 细分, p.data());
	p.push_back({ -高_半径.x * 0.5f, 0.0f, 0.0f });
	p.push_back({ 高_半径.x * 0.5f, 0.0f, 0.0f});

	std::vector<uint32> index(细分*12);
	for (uint32 i = 0; i < 细分; ++i) {
		if (i) {
			index[i*6] = p.size() - 2;
			index[i*6 + 1] = i - 1;
			index[i * 6 + 2] = i;

			index[i * 6 + 3] = p.size() - 1;
			index[i * 6 + 4] = 细分 + i - 1;
			index[i * 6 + 5] = 细分 + i;


			index[细分 * 6 + i * 6    ] = 细分 + i - 1;
			index[细分 * 6 + i * 6 + 1] = i-1;
			index[细分 * 6 + i * 6 + 2] = i;
			index[细分 * 6 + i * 6 + 3] = 细分 + i - 1;
			index[细分 * 6 + i * 6 + 4] = i;
			index[细分 * 6 + i * 6 + 5] = 细分 + i;
		}
		else {
			index[0] = p.size() - 2;
			index[1] = 0;
			index[2] = 细分-1;

			index[3] = p.size() - 1;
			index[4] = 细分 * 2 - 1;
			index[5] = 细分;


			index[细分 * 6 + 0] = 细分*2 - 1;
			index[细分 * 6 + 1] = 细分 - 1;
			index[细分 * 6 + 2] = 0;
			index[细分 * 6 + 3] = 细分*2 - 1;
			index[细分 * 6 + 4] = 0;
			index[细分 * 6 + 5] = 细分;
		}

		/*index[细分 * 6 + i*6 + 0] = 细分 * 2 + i - 1;
		index[细分 * 6 + i*6 + 1] = 细分 + i - 1;
		index[细分 * 6 + i*6 + 2] = i;
		index[细分 * 6 + i*6 + 3] = 细分 * 2 - 1;
		index[细分 * 6 + i*6 + 4] = 细分 + i;
		index[细分 * 6 + i*6 + 5] = 细分 * 2 + i;*/
	}

	mesh->f_fill顶点(p.data(), p.size());
	mesh->f_fill法线(p);
	f_me_fill索引(mesh, index);

	return obj;
}

S_物体* f_创建球体物体(const float32 半径, uvec2 细分, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建(E_物体类型::t_网格物体, 0, ctx);
	auto* mesh = f_ob_getMesh(obj, E_物体网格元素类型::e_MT_面);

	uint32 经度细分 = 细分.x;
	uint32 维度细分 = 细分.y;
	if (经度细分 < 3) 经度细分 = 3;
	if (维度细分 < 3) 维度细分 = 3;


	std::vector<vec3> 顶点(经度细分 * 维度细分 + 2);
	std::vector<vec3> 法线(经度细分 * 维度细分 + 2);



	float32* p顶点 = (float32*)&顶点[0];

	顶点[0].x = 0.0;
	顶点[0].y = -半径;
	顶点[0].x = 0.0;

	vec3_填充(&法线[0], 0.0, -1.0, 0.0);



	S_Tranform 变换;
	f_TranformInit(变换);
	矩阵_创建缩放矩阵v(缩放矩阵, (float32*)&变换.scale);

	//float32 坐标X[3] = { -半径, 0.0, 0.0 };
	float32	Normal[4] = { 0.0, -1.0, 0.0, 1.0 };
	vec4	NewNormal = { 0.0, 1.0, 0.0, 0.0 };
	float32	坐标Z[4] = { 0.0, -半径, 0.0, 1.0 };
	float32	原点坐标[4] = { 0.0, 0.0, 0.0 , 0.0 };
	矩阵_创建移动矩阵v(移动矩阵, 坐标Z);
	for (uint16 纬度 = 0; 纬度 < 维度细分; ++纬度) {
		float32 当前维度 = (180.0 / (float32)维度细分) * (float32)(纬度 + 1);

		矩阵_创建X旋转矩阵(X旋转矩阵, 当前维度);
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 id = 纬度 * 经度细分 + 经度 + 1;

			float32 当前经度 = (360.0 / (float32)经度细分) * (float32)(经度);

			float32 RY[3] = { 当前维度, 当前经度, 0.0 };
			矩阵_创建Y旋转矩阵(Y旋转矩阵, 当前经度);
			矩阵_创建单位矩阵4X4(变换矩阵);
			
			Mat4X4_相乘(&变换矩阵, &Y旋转矩阵);
			Mat4X4_相乘(&变换矩阵, &X旋转矩阵);


			vec3_填充(原点坐标, 0.0);
			vec4_填充(&NewNormal, 0.0);
			MAT变换坐标4(&变换矩阵, 坐标Z, 原点坐标);
			MAT变换坐标4(&变换矩阵, Normal, &NewNormal);
			顶点[id].x = 原点坐标[0];
			顶点[id].y = 原点坐标[1];
			顶点[id].z = 原点坐标[2];

			vec3_填充(&法线[id], &NewNormal);
		}
	}

	顶点[经度细分 * 维度细分 + 1].x = 0.0;
	顶点[经度细分 * 维度细分 + 1].y = 半径;
	顶点[经度细分 * 维度细分 + 1].x = 0.0;
	mesh->f_fill顶点(顶点.data(), 顶点.size());
	//f_填充顶点数据(mesh, 顶点);
	

	vec3_填充(&法线[经度细分 * 维度细分 + 1], 0.0, 1.0, 0.0);
	mesh->f_fill法线(法线);
	//f_填充法线数据(mesh, 法线);
	


	std::vector<uint32> 索引(顶点.size() * 6);

	//底部盖
	索引[0] = 0;
	uint32 V1 = 0;
	uint32 V2 = 1;
	uint32 V3 = 2;
	uint32 V4 = 0;
	uint32 index = 0;
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {

		索引[index + 0] = 0;
		索引[index + 1] = V2;
		索引[index + 2] = V3;

		index += 3;

		V2 += 1; if (V2 >= 经度细分 + 2) V2 = 1;
		V3 += 1; if (V3 >= 经度细分 + 2) V3 = 2;
	}
	索引[index - 2] = 0;

	//================== 中间 ====================
	for (uint16 纬度 = 0; 纬度 < 维度细分 - 2; ++纬度) {
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 idL1 = 纬度 * 经度细分 + 经度 + 2;
			uint16 idL2 = (纬度 + 1) * 经度细分 + 经度 + 2;


			V1 = idL1; V2 = idL2; V3 = idL1 + 1; V4 = idL2 + 1;

			if (uint32(经度 + 1) >= 经度细分) V3 = 纬度 * 经度细分 + 2;
			if (uint32(经度 + 1) >= 经度细分) V4 = (纬度 + 1) * 经度细分 + 2;


			索引[index + 0] = V1;
			索引[index + 1] = V2;
			索引[index + 2] = V3;
			index += 3;

			索引[index + 0] = V3;
			索引[index + 1] = V2;
			索引[index + 2] = V4;
			index += 3;

		}
	}

	//
	V1 = 经度细分 * 维度细分 + 1;

	//顶部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		uint16 idL1 = (维度细分 - 2) * 经度细分 + 经度 + 2;
		V2 = idL1; V3 = idL1 + 1;
		if (uint32(经度 + 1) >= 经度细分) V3 = (维度细分 - 2) * 经度细分 + 2;

		索引[index + 0] = V2;
		索引[index + 1] = V1;
		索引[index + 2] = V3;

		index += 3;
	}
	索引[index - 1] = 经度细分 * 维度细分 + 1;

	
	f_me_fill索引(mesh, 索引);
	//f_填充索引数据(mesh, 索引);
	//mesh->f_填充绘制间隔(vector<ui2_32>({ { 0, uint32(索引.size()) } }));

	return obj;
}



void f_ob_构建骨骼虚拟体实例ID(S_物体* ob, uint32& d) {
	ob->m_实例ID = d;
	++d;
	for (auto& e : ob->m_子物体) {
		f_ob_构建骨骼虚拟体实例ID(static_cast<S_物体*>(e), d);
	}
	if (!ob->m_实例ID) f_ob_set实例数量(ob, d);
}

static void f_ob_递归绑定子骨头骨骼对象(S_物体* ob, S_骨架* 骨骼, uint32& d) {
	if (ob->m_Type == E_物体类型::t_骨骼) {
		ob->m_骨架 = 骨骼;
		ob->m_实例ID = d;
		++d;
	}
	for (auto& e : ob->m_子物体) {
		auto* ob = static_cast<S_物体*>(e);
		f_ob_递归绑定子骨头骨骼对象(static_cast<S_物体*>(e), 骨骼, d);
	}
}

void f_ob_构建骨骼(S_物体* ob, S_物体* 骨骼物体, S_物体* 骨节物体, S_物体* 骨骼辅助虚拟物体) {
	S_骨架* 骨架 = f_ob_from骨架(ob);

	C_骨骼管理::m_骨骼容器.insert(骨架);
	uint32 num = 0;
	f_ob_递归绑定子骨头骨骼对象(ob, 骨架, num);

	//f_gbuf_resize(骨架->m_骨骼长度, num);
	f_bm_resize(骨架->m_姿态, num);
	//f_gbuf_resize(骨架->m_初始姿态, num);
	//f_gbuf_resize(骨架->m_变换姿态, num);


	
	骨架->m_骨头数量 = num;
	f_ob_fill实例(骨骼物体, num);

	num += ob->m_子物体.size();
	f_ob_fill实例(骨节物体, num);

}

void f_ob_绑定网格骨骼(S_物体* ob, S_物体* bonse, uint32 mesh_loc) {
	if (mesh_loc < ob->m_DataNum) {
		(S_Mesh*)ob->m_Data[mesh_loc];

		ob->m_骨架 = bonse->m_骨架;
	}
}







S_摄像机* f_ob_创建摄像机(S_设备环境 ctx, E_绘图API engineType) {
	S_摄像机* camera = new S_摄像机(ctx);

	//camera->m_变换矩阵.m_MemOffset = f_buf_galloc(S_物体::g_变换矩阵[ctx.m_逻辑设备.ID], 3);
	//camera->m_变换矩阵.m_Buf = S_物体::g_变换矩阵[ctx.m_逻辑设备.ID];
	camera->f_LookAt({ 0.0f, 0.0f, -5.0f }, { 0.0f,0.0f,0.0f }, { 0.0f,1.0f,0.0f });
	camera->f_set透视投影(45.0f, 1.0f, {0.01f, 6000.0f});

	return camera;
}

void f_ob_销毁摄像机(S_摄像机* camera) {
	//f_buf_gfree(camera->m_变换矩阵.m_Buf, camera->m_变换矩阵.m_MemOffset);
	f_buf_release板载缓存(camera->m_投影矩阵);
	delete camera;
}



void f_ob_link物体数据(S_物体* ob, S_物体* froObj) {
	//ob->m_网格模型 = froObj->m_网格模型;
	for (auto& e : froObj->m_网格模型) {
		S_网格包 网格包;
		网格包.m_常量推送.m_常量推送 = calloc(1, e.m_常量推送.m_常量推送字节大小);
		网格包.m_常量推送.m_常量推送字节大小 = e.m_常量推送.m_常量推送字节大小;
		网格包.m_常量推送.m_常量推送绑定阶段 = e.m_常量推送.m_常量推送绑定阶段;

		网格包.m_深度偏移 = e.m_深度偏移;
		网格包.m_多维材质槽 = e.m_多维材质槽;
		网格包.m_Mesh = e.m_Mesh;

		ob->m_网格模型.emplace_back(网格包);
	}
}

//S_物体* f_ob_copy到新物体(S_设备环境& ctx, S_物体* froObj) {
//	S_物体* ob = f_ob_创建物体(froObj->m_Type, froObj, ctx);
//	
//	ob->m_变换 = froObj->m_变换;
//	
//	if (froObj->m_位置) ob->m_位置 = f_an_拷贝曲线通道(froObj->m_位置);
//	if (froObj->m_旋转) ob->m_旋转 = f_an_拷贝曲线通道(froObj->m_旋转);
//	if (froObj->m_缩放) ob->m_缩放 = f_an_拷贝曲线通道(froObj->m_缩放);
//
//
//	ob->m_实例ID = froObj->m_实例ID;
//	ob->m_是否实例 = froObj->m_是否实例;
//
//	if (froObj->m_UserData) {
//		switch (froObj->m_Type) {
//			case E_物体类型::t_骨骼: {
//				S_物体* 骨节 = f_ob_copy到新物体(ctx, (S_物体*)froObj->m_UserData);
//				ob->m_UserData = 骨节;
//				break;
//			}
//			default:
//				break;
//		}
//	}
//
//	f_ob_link物体数据(ob, froObj);
//	f_ob_set实例数量(ob, ob->m_变换矩阵.m_Mem.m_数量);
//	
//
//	for (auto& e : froObj->m_子物体) {
//		auto* 新子物体 = f_ob_copy到新物体(ctx, static_cast<S_物体*>(e));
//		f_ob_add子物体(ob, 新子物体);
//	}
//
//	return ob;
//}

void f_ob_set数据槽数量(S_物体* ob, uint32 num) {
	ob->m_网格模型.resize(num);
	return;

	for (uint32 i = num; i < ob->m_DataNum; ++i) {
		f_bm_erase(ob->m_实例颜色[i]);
	}

	ob->m_实例颜色.resize(num);
	for (uint32 i = 0; i < num; ++i) {
		ob->m_实例颜色[i] = f_bm_alloc(f_buf_getGlobal().g_物体颜色[i], 1);
		f_bm_at<uint32>(ob->m_实例颜色[i], 0) = f_PackData4X8({ 200,200,200,255 });
	}

	if (ob->m_DataNum != num) {
		ob->f_setDataNum(num);
	}
}

void f_ob_set安装网格(S_物体* ob, std::vector<S_网格包>& pack) {
	ob->m_网格模型 = pack;
}

void f_ob_set数据(S_物体* Obj, void* data, uint8 loc) {
	assert(loc < Obj->m_DataNum);
	Obj->f_setData(data, loc);
}

S_网格包& f_ob_set数据(S_物体* ob, S_Mesh* me, uint8 loc) {
	assert(loc < ob->m_网格模型.size());
	ob->m_网格模型[loc].m_Mesh = me;
	++me->m_引用计数;
	return ob->m_网格模型[loc];
}

S_网格包& f_ob_get数据(S_物体* ob, uint8 loc) {
	return ob->m_网格模型[loc];
}
const S_网格包& f_ob_get数据(const S_物体* ob, uint8 loc) {
	return ob->m_网格模型[loc];
}

std::vector<S_网格包>& f_ob_get网格包(S_物体* ob) {
	return ob->m_网格模型;
}

const std::vector<S_网格包>& f_ob_get网格包(const S_物体* ob) {
	return ob->m_网格模型;
}

void f_ob_fill实例ID(S_物体* ob) {
	uint32 num = ob->m_子物体.size();

	for (uint32 i = 0; i < num; ++i) {
		auto* so = static_cast<S_物体*>(ob->m_子物体[i]);
		so->m_实例ID = i;
		//so->m_父物体 = ob;
	}
}

void f_ob_fill实例(S_物体* ob, uint32 num) {
	uint32 已有数量 = ob->m_子物体.size();

	for (uint32 i = num; i < 已有数量; ++i) {
		delete ob->m_子物体[i];
	}
	f_ob_set实例数量(ob, num);

	for (uint32 i = 已有数量; i < num; ++i) {
		ob->m_子物体[i] = new S_物体(E_物体类型::t_实例);
		ob->m_子物体[i]->m_父对象 = ob;
	}

	f_ob_fill实例ID(ob);
}

void f_ob_set为实例(S_物体* Obj) {
	Obj->m_是否实例 = true;
	//Obj->m_Type = E_物体类型::t_实例;
	Obj->m_DataNum = 0;
	if(Obj->m_Data) free(Obj->m_Data);
	Obj->m_Data = nullptr;
}

void f_ob_set物体数据可视(S_物体* Obj, uint8 loc, bool 是否可视)  {
	((S_Mesh*)(Obj->m_Data[loc]))->m_显示 = 是否可视;
}


void f_ob_set线宽(S_物体* Obj, float32 h, uint8 loc)  {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	if (mesh) {
		mesh->m_线宽 = h;
	}
	else if (Obj->m_DataNum) {
		((S_Mesh*)(Obj->m_Data[loc]))->m_线宽 = h;
	}
}

void f_ob_set细分(S_物体* Obj, uint32 次数, uint8 loc)  {
	//if (Obj->m_GPU参数布局[loc].m_参数数量 >= 3) {
	//	uvec3 dim = { 次数 ,次数 ,次数 };
	//	f_buf_fill板载缓存<uvec3>(Obj->m_GPU参数布局[loc].m_参数槽[2], &dim, 1, E_板载缓存类型::e_UBO);
	//}
}

void f_ob_set网格可视(S_物体* ob, bool show, uint8 loc) {
	((S_Mesh*)(ob->m_Data[loc]))->m_显示 = show;
}

void f_ob_set附属类型(S_物体* ob, E_物体类型 类型) {
	ob->m_附属类型 = 类型;
}

E_物体类型 f_ob_get附属类型(S_物体* ob) {
	return ob->m_附属类型;
}

void f_ob_set材质(S_物体* ob, S_材质管线* mtl, uint8 loc, int32 多维子元素)  {
	if (ob->m_网格模型[loc].m_多维材质槽.size() >= 多维子元素) {
		ob->m_网格模型[loc].m_多维材质槽.push_back(mtl);
	}
	else {
		ob->m_网格模型[loc].m_多维材质槽[多维子元素] = mtl;
	}

	ob->m_网格模型[loc].m_常量推送;
	ob->m_isUpdate = true;
	
}


void f_ob_set颜色2(S_物体* Obj, S_RGBA8UI color, uint32 offset, uint8 槽) {
	switch (Obj->m_Type) {
		case E_物体类型::t_包:
		case E_物体类型::t_空:
		case E_物体类型::t_实例:
			if (Obj->m_父对象) {
				f_ob_set颜色2(static_cast<S_物体*>(Obj->m_父对象), color, offset, 槽);
				return;
			}
			
			//Obj = Obj->m_父物体;
			//offset = Obj->m_实例ID;
			break;

		case E_物体类型::t_线段:
		case E_物体类型::t_点光源:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光:
		case E_物体类型::t_平行光:

		case E_物体类型::t_粒子系统:
		case E_物体类型::t_骨节:
		case E_物体类型::t_骨架:
		case E_物体类型::t_骨骼:
		case E_物体类型::t_虚拟体:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			//Obj->m_实例颜色[槽].m_Buf->m_分配块内存锁.lock();
			//f_buf_UI32_at(Obj->m_实例颜色[槽], offset) = f_PackData4X8(color);
			//Obj->m_实例颜色[槽].m_Buf->m_分配块内存锁.unlock();
			break;
		}
		default:
			std::cout<<"物体类型设置颜色错误"<<std::endl;
			break;
	}
}

void f_ob_set颜色(S_物体* ob, const S_RGBA8UI& color) {
	for(uint32 i=0; i<ob->m_DataNum; ++i){
		ob->m_实例颜色[i].m_Buf->m_分配块内存锁.lock();

		f_buf_UI32_at(ob->m_实例颜色[i], 0) = f_PackData4X8(color);

		ob->m_实例颜色[i].m_Buf->m_分配块内存锁.unlock();
	}
}

void f_ob_set粒子数量(S_物体* Obj, uint32 num) {
	auto psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		f_set粒子数量(psys->m_粒子, num);
	}
}

void f_ob_set粒子位置(S_物体* Obj, const vec3* l, uint32 num) {
	auto psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		f_set粒子位置(psys->m_粒子, l, num);
	}
}

void f_ob_set粒子速度(S_物体* Obj, const vec3* v, uint32 num)
{
}

void f_ob_set粒子旋转(S_物体* Obj, const vec3* r, uint32 num)
{
}

void f_ob_set粒子大小(S_物体* Obj, const vec3* s, uint32 num)
{
}

void f_ob_set粒子渲染物体(S_物体* Obj, E_粒子绘制类型 绘制类型) {
	S_粒子系统* psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		psys->m_粒子;
	}
}

//void f_ob_set粒子数量(S_物体* ob, uint32 num) {
//	S_粒子系统* psys = dynamic_cast<S_粒子系统*>(ob);
//	psys->m_粒子->m_Count = num;
//
//	f_ob_set粒子数量(psys, num);
//}

S_粒子系统配置* f_ob_fromParticle(S_物体* ob, uint32 loc) {
	S_粒子系统* psys = dynamic_cast<S_粒子系统*>(ob);
	return psys->m_粒子;
}

void f_ob_copy骨骼(S_物体* d_ob, const S_物体* s_ob) {
	S_骨骼* 源骨骼 = f_ob_from骨骼(s_ob);
	S_骨骼* 骨骼 = f_ob_from骨骼(d_ob);

	骨骼->m_长度 = 源骨骼->m_长度;
	骨骼->m_旋转 = 源骨骼->m_旋转;
	骨骼->m_动态旋转 = 源骨骼->m_动态旋转;
	
	骨骼->m_封套S内半径 = 源骨骼->m_封套S内半径;
	骨骼->m_封套E内半径 = 源骨骼->m_封套E内半径;
	
	骨骼->m_封套S外半径 = 源骨骼->m_封套S外半径;
	骨骼->m_封套E外半径 = 源骨骼->m_封套E外半径;

	骨骼->m_自动封套大小 = 源骨骼->m_自动封套大小;


	S_骨节* 源骨节 = f_ob_from骨节(源骨骼);
	S_骨节* 骨节 = f_ob_from骨节(骨骼);

	骨节->m_Type = 源骨节->m_Type;
	骨节->m_封套大小 = 源骨节->m_封套大小;
	骨节->m_骨节初始尾坐标 = 源骨节->m_骨节初始尾坐标;

}

S_物体* f_ob_copy(S_设备环境& ctx, S_物体* ob, bool 链接) {
	S_物体* newObj = f_ob_创建(ctx, ob->m_Type);

	newObj->m_变换 = ob->m_变换;
	newObj->m_扩展属性 = ob->m_扩展属性;
	if (链接) {
		f_ob_link物体数据(newObj, ob);

		newObj->m_UserData = ob->m_UserData;
	}
	else {
		if (ob->m_位置) newObj->m_位置 = f_an_拷贝曲线通道(ob->m_位置);
		if (ob->m_旋转) newObj->m_旋转 = f_an_拷贝曲线通道(ob->m_旋转);
		if (ob->m_缩放) newObj->m_缩放 = f_an_拷贝曲线通道(ob->m_缩放);

		
		switch (ob->m_Type) {
			case E_物体类型::t_骨骼:
				f_ob_copy骨骼(newObj, ob);
				goto To_拷贝网格;
				break;

			case E_物体类型::t_多边形: {
				S_多边形* src = (S_多边形*)ob->m_多边形;
				f_surface_copy(src, (S_多边形*)newObj->m_多边形);
			}
			//newObj->m_UserData = f_surface_copy((S_多边形*)ob->m_UserData);
			case E_物体类型::t_网格物体: {
				To_拷贝网格:
				f_ob_set数据槽数量(newObj, ob->m_DataNum);
				for (uint32 i = 0; i < ob->m_DataNum; ++i) {
					auto* 源网格 = f_ob_getMesh(ob, i);
					
					auto* 新网格 = f_surface_创建网格对象(源网格, ctx, ctx.m_支持光追, E_网格数据枚举::e_Mesh_Vulkan);
					f_surface_Copy(新网格, 源网格);

					f_ob_set数据(newObj, 新网格, i);
					for (uint32 k = 0; k < ((S_Mesh*)ob->m_Data[i])->m_多维材质数量; ++k) {
						f_ob_set材质(newObj, ((S_Mesh*)ob->m_Data[i])->m_多维材质槽[k].m_Material, i);
					}
					
					f_bm_copy(newObj->m_实例颜色[i], ob->m_实例颜色[i]);
				}
				break;
			}
			default:
				break;
		}
	}

	newObj->m_实例ID		= ob->m_实例ID;
	newObj->m_是否实例		= ob->m_是否实例;
	newObj->m_视口显示模式	= ob->m_视口显示模式;


	for (auto& e : ob->m_子物体) {
		auto* 新子物体 = f_ob_copy(ctx, static_cast<S_物体*>(e), 链接);
		f_ob_add子物体(newObj, 新子物体);
	}

	return newObj;
}

void f_ob_copyData(S_物体* ob, S_物体* 源物体, bool 链接) {
	f_ob_改变物体类型(ob, 源物体->m_Type);

	ob->m_变换 = 源物体->m_变换;

	if (源物体->m_位置) ob->m_位置 = f_an_拷贝曲线通道(源物体->m_位置);
	if (源物体->m_旋转) ob->m_旋转 = f_an_拷贝曲线通道(源物体->m_旋转);
	if (源物体->m_缩放) ob->m_缩放 = f_an_拷贝曲线通道(源物体->m_缩放);

	ob->m_实例ID = 源物体->m_实例ID;

	if (链接) {
		f_ob_link物体数据(ob, 源物体);
	}
	else {
		//f_ob_copy物体数据(ob);
	}
}

void f_ob_copyIK(S_骨骼IK* d_ik, S_骨骼IK* s_ik) {
	d_ik->m_深度 = s_ik->m_深度;
	d_ik->m_骨骼段数 = s_ik->m_骨骼段数;
	d_ik->m_迭代次数 = s_ik->m_迭代次数;

	d_ik->m_IK类型 = s_ik->m_IK类型;
	d_ik->m_使用骨节坐标 = s_ik->m_使用骨节坐标;
}

S_Mesh* f_ob_fromTranformMesh(S_物体* froObj, uint32 loc) {
	S_Mesh* mesh = nullptr;
	switch (froObj->m_Type) {
	case E_物体类型::t_网格物体:
	case E_物体类型::t_多边形:
		if (froObj->m_Data) {
			mesh = f_surface_创建网格对象(E_网格数据枚举::e_Mesh_CPU);
			f_surface_Copy(mesh, (S_Mesh*)(froObj->m_Data[loc]));
			f_surface_变换(mesh, froObj->m_变换);
		}
		break;
	default:
		break;
	}
	
	return mesh;
}


S_灯光场景数据* f_ob_getLigth(const S_物体* ob, uint32 loc) {
	assert(ob->m_Type == E_物体类型::t_区域光);
	return (S_灯光场景数据*)(ob->m_Data[0]);
}



S_LightParallel* f_ob_fromParallelLigth(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_平行光) {
		return (S_LightParallel*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LightSpot* f_ob_fromLigthSpot(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_聚光灯) {
		return (S_LightSpot*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LightPoint* f_ob_fromLigthPoint(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_点光源) {
		return (S_LightPoint*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LightArea* f_ob_fromAreaLigth(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_区域光) {
		return (S_LightArea*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

//S_灯光场景数据* f_ob_fromLigthSceneData(S_物体* froObj) {
//	switch (froObj->m_Type) {
//	case E_物体类型::t_平行光:
//	case E_物体类型::t_聚光灯:
//	case E_物体类型::t_点光源:
//	case E_物体类型::t_区域光:
//		return (S_灯光场景数据*)(froObj->m_Data[1]);
//	default:
//		break;
//	}
//	return nullptr;
//}

uint32 f_ob_get数量层数量(S_物体* ob) {
	return ob->m_DataNum;
}

uint32 f_ob_get实例数量(S_物体* ob) {
	return ob->m_变换矩阵.m_Mem.m_数量;
}

uint32 f_ob_get顶点数量(S_物体* Obj) {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	return mesh->m_网格->f_get顶点数量();
}

float32 f_ob_get最大半径(S_物体* Obj) {

	return float32();
}

S_Sphere f_ob_get范围(S_物体* Obj) {

	return S_Sphere();
}

S_物体* f_ob_get子对象(S_物体* Obj, uint32 offset) {
	if (offset >= Obj->m_子物体.size()) {
		return nullptr;
	}
	return static_cast<S_物体*>(Obj->m_子物体[offset]);
}

S_物体* f_ob_get实例ID对象(S_物体* Obj, uint32 ID) {
	uint32 num = Obj->m_子物体.size();
	auto* obs = Obj->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		if (static_cast<S_物体*>(obs[i])->m_实例ID == ID) {
			return static_cast<S_物体*>(obs[i]);
		}
	}

	for (uint32 i = 0; i < num; ++i) {
		S_物体* ob = f_ob_get实例ID对象(static_cast<S_物体*>(obs[i]), ID);
		if (ob) return ob;
	}
	return nullptr;
}

S_物体* f_ob_get父变换对象(S_物体* Obj) {
	if (Obj->m_父对象) {
		if (static_cast<S_物体*>(Obj->m_父对象)->m_变换矩阵.m_Mem.m_数量) {
			return static_cast<S_物体*>(Obj->m_父对象);
		}
		else {
			return f_ob_get父变换对象(static_cast<S_物体*>(Obj->m_父对象));
		}
	}
	return nullptr;
}

vec3 f_ob_get全局坐标(S_物体* Obj, uint32 ID) {
	if (Obj->m_变换矩阵.m_Mem.m_数量) {
		return f_buf_Mat44_at(Obj->m_变换矩阵, ID) * vec3{ 0,0,0 };
	}
	else {
		if (Obj->m_父对象) {
			return f_ob_get全局坐标(static_cast<S_物体*>(Obj->m_父对象), ID);
		}
	}
	return Obj->f_get位置();
}

S_物体* f_ob_from实例对象取父对象(S_物体* Obj) {
	if (Obj->m_父对象) {
		switch (Obj->m_Type) {
			case E_物体类型::t_实例:
			//case E_物体类型::t_骨架:
			//case E_物体类型::t_骨骼:
			//case E_物体类型::t_虚拟体:
				return f_ob_from实例对象取父对象(static_cast<S_物体*>(Obj->m_父对象));
			default:
				break;
		}
	}
	
	return Obj;
}

E_物体类型 f_ob_get可视对象类型(S_物体* Obj) {
	//if (f_ob_fromMesh(Obj)) {
	//	return Obj->m_Type;
	//}

	switch (Obj->m_Type)
	{
	//case E_物体类型::t_骨架:
	//case E_物体类型::t_骨骼:
	case E_物体类型::t_物体包: {
		if(Obj->m_子物体.size()) return f_ob_get可视对象类型(static_cast<S_物体*>(Obj->m_子物体.front()));
	}
	default:
		break;
	}

	return Obj->m_Type;
}

uint64 f_ob_get子物体数量(S_物体* Ob, bool 包括子集) {
	return Ob->m_子物体.size();
}

S_物体* f_ob_以类型查找子物体(S_物体* ob, E_物体类型 type) {
	if(ob->m_Type == type) return ob;
	uint32 num = ob->m_子物体.size();
	auto** data = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		S_物体* findOb = f_ob_以类型查找子物体(static_cast<S_物体*>(data[i]), type);
		if (findOb) {
			return findOb;
		}
	}
	return nullptr;
}




uint32 f_ob_add子物体(S_物体* 父, S_物体* 子, uint32 loc) {
	if (父) {
		if (loc >= 父->m_子物体.size()) {
			loc = 父->m_子物体.size();
			//子->m_实例ID = 父->m_子物体.size();
			父->m_子物体.push_back(子);
		}
		else {
			父->m_子物体[loc] = 子;
			//子->m_实例ID = loc;
		}

		子->m_父对象 = 父;
		父->m_isUpdate = true;

		switch (子->m_Type) {
			case E_物体类型::t_区域光:
			case E_物体类型::t_点光源:
			case E_物体类型::t_聚光灯:
			case E_物体类型::t_平行光:
			case E_物体类型::t_实例:
			//case E_物体类型::t_虚拟体:
				子->m_实例ID = loc;
				break;
			default:
				break;
		}
	}
	return loc;
}

void f_ob_add实例物体(S_物体* 父, S_物体* 子物体, uint32 loc) {
	子物体->m_实例ID = 父->m_子物体.size();

	f_ob_add子物体(父, 子物体, loc);

	if (父->m_变换矩阵.m_Mem.m_数量 < 父->m_子物体.size()) {
		f_ob_添加矩阵(父);
	}
	子物体->m_是否实例 = true;
}

void f_ob_ins实例物体(S_物体* 父, uint32 实例ID, uint32 loc) {
	S_物体* ob = nullptr;
	if (loc >= 父->m_子物体.size()) {
		ob = f_ob_创建实例(父, loc);
		f_ob_add子物体(父, ob, loc);
	}
	ob->m_实例ID = 实例ID;
}

void f_ob_set实例物体(S_物体* 父, S_物体* 子, uint32 loc) {
	父->m_子物体[loc] = 子;
	子->m_实例ID = loc;
	子->m_父对象 = 父;
	子->m_是否实例 = true;
}

void f_ob_clear子物体(S_物体* 父, uint64 s, uint64 e) {
	uint32 num = 父->m_子物体.size();
	if (!num) return;
	if (e > num) {
		e = num;
	}

	for (uint32 i = s; i < e; ++i) {
		父->m_子物体[i]->m_父对象 = nullptr;
		static_cast<S_物体*>(父->m_子物体[i])->m_父级变换关系 = E_父级变换关系::e_变换关系_保持偏移;
	}

	auto iter_s = 父->m_子物体.begin() + s;
	auto iter_e = 父->m_子物体.begin() + e;
	
	父->m_子物体.erase(iter_s, iter_e);
}

void f_ob_从父物体中移除(S_物体* ob) {
	if (ob->m_父对象) {
		uint32 num = ob->m_父对象->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			if (ob == ob->m_父对象->m_子物体[i]) {
				ob->m_父对象->m_子物体.erase(ob->m_父对象->m_子物体.begin() + i);
				break;
			}
		}
		f_ob_set实例数量((S_物体*)ob->m_父对象, ob->m_父对象->m_子物体.size(), false);
		((S_物体*)ob->m_父对象)->m_isUpdate = true;
	}
}

void f_ob_销毁子物体(S_物体* 父, uint64 s, uint64 e) {
	uint32 num = 父->m_子物体.size();
	if (!num) return;
	if (e > num) {
		e = num;
	}


	f_ob_删除矩阵(父, s, e - s);
	for (uint32 i = s; i < e; ++i) {
		f_ob_销毁(static_cast<S_物体*>(父->m_子物体[i]));
	}

	auto iter_s = 父->m_子物体.begin() + s;
	auto iter_e = 父->m_子物体.begin() + e;

	父->m_子物体.erase(iter_s, iter_e);
	num = 父->m_子物体.size();
	for (uint32 i = s; i < num; ++i) {
		static_cast<S_物体*>(父->m_子物体[i])->m_实例ID = i;
	}
}

void f_ob_清除子物体(S_物体* 父) {
	for (auto& e : 父->m_子物体) {
		e->m_父对象 = nullptr;
	}
	父->m_子物体.clear();
}



vec3 f_ob_getLoc(S_物体* ob, uint32 id) {
	return ob->f_get位置();
}

vec3 f_ob_getRot(S_物体* ob, uint32 id) {
	return ob->f_get旋转();
}

vec3 f_ob_getScale(S_物体* ob, uint32 id) {
	return ob->f_get缩放();
}


void f_ob_setLoc(S_物体* ob, const vec3& loc, uint32 id) {
	ob->m_isUpdate = true;
	ob->f_set位置(loc, id);
}

void f_ob_setRot(S_物体* ob, const vec3& rot, uint32 id) {
	ob->m_isUpdate = true;
	ob->f_set旋转(rot, id);
}

void f_ob_setScale(S_物体* ob, const vec3& scal) {
	ob->m_isUpdate = true;
	ob->f_set缩放(scal);
}

void f_ob_setScale(S_物体* ob, const vec3& scal, uint32 id) {
	static_cast<S_物体*>(ob->m_子物体[id])->f_set缩放(scal, id);
}

void f_ob_setTranform(S_物体* ob, const S_Tranform& tran) {
	ob->m_变换 = tran;
	ob->m_isUpdate = true;
}

void f_ob_Load物体(S_物体* ob, FILE* f) {
	ob->m_Name = f_file_读取字符串(f);
	fread(&ob->m_Type, sizeof(E_物体类型), 1, f);

	std::vector<vec3> 变换(3);
	file_读取序列到文件(f, &变换);
	ob->m_变换.position = 变换[0];
	ob->m_变换.rotation = 变换[1];
	ob->m_变换.scale = 变换[2];


	ob->m_位置 = f_an_Load通道(f);
	ob->m_旋转 = f_an_Load通道(f);
	ob->m_缩放 = f_an_Load通道(f);

	if(ob->m_位置) ob->m_位置->ObPtr = ob;
	if(ob->m_旋转) ob->m_旋转->ObPtr = ob;
	if(ob->m_缩放) ob->m_缩放->ObPtr = ob;
}

void f_ob_Save物体(S_物体* ob, FILE* f) {
	f_file_保存字符串(f, ob->m_Name);
	fwrite(&ob->m_Type, sizeof(E_物体类型), 1, f);

	std::vector<vec3> 变换;
	变换.push_back(ob->m_变换.position);
	变换.push_back(ob->m_变换.rotation);
	变换.push_back(ob->m_变换.scale);
	file_写入序列到文件(f, 变换);


	f_an_Save通道(ob->m_位置, f);
	f_an_Save通道(ob->m_旋转, f);
	f_an_Save通道(ob->m_缩放, f);
}




const uint8* f_ob_Load物体(S_设备环境& ctx, S_物体** ob, const uint8* 块) {
	E_物体类型 物体类型;
	std::u16string 物体名称;

	块 = f_文件块_读字符串(块, 物体名称);
	块 = f_文件块_读数据块(块, 物体类型);

	ob[0] = f_ob_创建(ctx, 物体类型);
	ob[0]->m_Name = 物体名称;


	块 = f_文件块_读数据块(块, ob[0]->m_变换.position);
	块 = f_文件块_读数据块(块, ob[0]->m_变换.rotation);
	块 = f_文件块_读数据块(块, ob[0]->m_变换.scale);

	块 = f_an_Load通道(&ob[0]->m_位置, 块);
	块 = f_an_Load通道(&ob[0]->m_旋转, 块);
	块 = f_an_Load通道(&ob[0]->m_缩放, 块);

	if (ob[0]->m_位置) ob[0]->m_位置->ObPtr = ob[0];
	if (ob[0]->m_旋转) ob[0]->m_旋转->ObPtr = ob[0];
	if (ob[0]->m_缩放) ob[0]->m_缩放->ObPtr = ob[0];

	块 = f_文件块_读数据块(块, ob[0]->m_视口显示模式);

	ob[0]->m_视口显示模式 = f_物体视口全局显示模式矫正(ob[0]->m_Type, ob[0]->m_视口显示模式);
	return 块;
}

void f_ob_Save物体(const S_物体* ob, S_UI8Array* 块) {
	
	f_文件块_写字符串(块, ob->m_Name);
	f_文件块_写数据块(块, ob->m_Type);
	
	f_文件块_写数据块(块, ob->m_变换.position);
	f_文件块_写数据块(块, ob->m_变换.rotation);
	f_文件块_写数据块(块, ob->m_变换.scale);
	
	f_an_Save通道(ob->m_位置, 块);
	f_an_Save通道(ob->m_旋转, 块);
	f_an_Save通道(ob->m_缩放, 块);

	f_文件块_写数据块(块, ob->m_视口显示模式);
}






const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx) {
	for (uint32 i = 0; i < obs->count; ++i) {
		//块 = f_ob_Load物体(obs->ptr_userData[i], 块);
	}
	return 块;
}

void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块) {
	for (uint32 i = 0; i < obs->count; ++i) {
		f_ob_Save物体(obs->ptr_userData[i], 块);
	}
}

const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx, bool 数据, fp_创建物体几何数据 模型创建回调) {
	bool 压缩 = false;
	块 = f_文件块_读数据块(块, 压缩);

	uint32 num = 0;
	块 = f_文件块_读数据块(块, num);

	f_core_array_resize((S_Array*)obs, num);

//#pragma omp parallel for
	for (int32 i = 0; i < obs->count; ++i) {
		if (!obs->ptr_userData[i]) {
			obs->ptr_userData[i] = f_ob_创建(ctx, E_物体类型::t_空);
		}
		
		//块 = f_ob_Load物体(obs->ptr_userData[i], 块);
		模型创建回调(obs->ptr_userData[i], ctx);

		if (数据) {
			
			f_ob_改变物体类型(obs->ptr_userData[i], obs->ptr_userData[i]->m_Type);
			switch (obs->ptr_userData[i]->m_Type) {
				case E_物体类型::t_网格物体: {
					块 = f_surface_网格读取(块, f_ob_getMesh(obs->ptr_userData[i], E_物体网格元素类型::e_MT_面), 压缩);
					break;
				}
				case E_物体类型::t_多边形: {
					S_多边形* poly = f_surface_创建多边形();
					块 = f_surface_多边形加载(块, poly, false);
					break;
				}
			}
		}
	}
	return 块;
}

void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块, bool 数据, bool 压缩) {
	f_文件块_写数据块(块, 压缩);

	f_文件块_写数据块(块, (uint32)obs->count);
	for (uint32 i = 0; i < obs->count; ++i) {
		f_ob_Save物体(obs->ptr_userData[i], 块);

		if (数据) {
			switch (obs->ptr_userData[i]->m_Type) {
				case E_物体类型::t_网格物体: {
					f_surface_网格保存(块, f_ob_getMesh(obs->ptr_userData[i], E_物体网格元素类型::e_MT_面), 压缩);
					break;
				}
				case E_物体类型::t_多边形: {
					f_surface_多边形保存(块, (S_多边形*)obs->ptr_userData[i]->m_UserData, false);
					break;
				}
			}
		}
	}
}

const uint8* f_ob_Load模型(S_物体** ob, const uint8* 块, S_设备环境& ctx, bool 数据, fp_创建物体几何数据 模型创建回调) {
	if (!ob[0]) {
		ob[0] = f_ob_创建(ctx, E_物体类型::t_空);
	}

	//块 = f_ob_Load物体(ob[0], 块);

	f_ob_改变物体类型(ob[0], ob[0]->m_Type);
	if(模型创建回调) 模型创建回调(ob[0], ctx);

	if (数据) {
		
		switch (ob[0]->m_Type) {
			case E_物体类型::t_网格物体: {
				块 = f_surface_网格读取(块, f_ob_getMesh(ob[0], E_物体网格元素类型::e_MT_面), false);
				break;
			}
			case E_物体类型::t_多边形: {
				if (ob[0]->m_UserData == nullptr) {
					ob[0]->m_UserData = f_surface_创建多边形();
				}
				块 = f_surface_多边形加载(块, (S_多边形*)ob[0]->m_UserData, false);
				
				break;
			}
		}

		ob[0]->m_isUpdate = true;
	}

	return 块;
}

void f_ob_Save模型(const S_物体* ob, S_UI8Array* 块, bool 数据) {
	f_ob_Save物体(ob, 块);

	if (数据) {
		switch (ob->m_Type) {
			case E_物体类型::t_网格物体: {
				f_surface_网格保存(块, f_ob_getMesh(ob, E_物体网格元素类型::e_MT_面), false);
				break;
			}
			case E_物体类型::t_多边形: {
				if (ob->m_UserData) {
					f_surface_多边形保存(块, (S_多边形*)(ob->m_UserData), false);
				}
				break;
			}
		}
	}
}

void f_ob_Save模型(const S_物体* ob, S_UI8Array* 块, bool 数据, E_物体类型 物体类型) {
	//f_ob_Save物体(ob, 块, 数据, 物体类型);

	if (数据) {
		switch (物体类型) {
			case E_物体类型::t_网格物体: {
				switch (ob->m_Type) {
					case E_物体类型::t_多边形:
					case E_物体类型::t_网格物体: {
						f_surface_网格保存(块, f_ob_getMesh(ob, E_物体网格元素类型::e_MT_面), false);
						break;
					}
				}
				break;
			}
			case E_物体类型::t_多边形: {
				switch (ob->m_Type) {
					case E_物体类型::t_多边形: {
						if (ob->m_UserData) {
							f_surface_多边形保存(块, (S_多边形*)(ob->m_UserData), false);
						}
						break;
					}
					case E_物体类型::t_网格物体: {
						//f_surface_网格保存(块, f_ob_fromMesh(ob, E_物体网格元素类型::e_MT_面), false);
						break;
					}
				}
				break;
			}
		}
	}
}




static const uint8* f_ob_递归加载物体(S_物体** ob, const uint8* 块, S_设备环境& ctx) {
	E_物体类型 type;
	块 = f_文件块_读数据块(块, type);
	ob[0] = f_ob_创建(type, nullptr, ctx);

	块 = f_解宽字符串(ob[0]->m_Name, 块);
	

	块 = f_文件块_读数据块(块, ob[0]->m_变换.position);
	块 = f_文件块_读数据块(块, ob[0]->m_变换.rotation);
	块 = f_文件块_读数据块(块, ob[0]->m_变换.scale);


	块 = f_an_Load通道(&ob[0]->m_位置, 块);
	块 = f_an_Load通道(&ob[0]->m_旋转, 块);
	块 = f_an_Load通道(&ob[0]->m_缩放, 块);


	if (ob[0]->m_位置) ob[0]->m_位置->ObPtr = ob;
	if (ob[0]->m_旋转) ob[0]->m_旋转->ObPtr = ob;
	if (ob[0]->m_缩放) ob[0]->m_缩放->ObPtr = ob;

	块 = f_文件块_读数据块(块, ob[0]->m_视口显示模式);
	ob[0]->m_视口显示模式 = f_物体视口全局显示模式矫正(ob[0]->m_Type, ob[0]->m_视口显示模式);

	switch (ob[0]->m_Type) {
		case E_物体类型::t_骨骼: {
			auto* 骨骼 = f_ob_from骨骼(ob[0]);

			bool IK物体 = false;
			块 = f_文件块_读数据块(块, IK物体);
			if (IK物体) {
				if(!骨骼->m_IK) 骨骼->m_IK = f_ob_创建IK();
				块 = f_ob_递归加载物体(&(骨骼->m_IK->m_末端坐标), 块, ctx);
			}
			break;
		}
		default:
			break;
	}

	uint64 count = 0;
	块 = f_文件块_读数据块(块, count);
	for (uint32 i = 0; i < count; ++i) {
		S_物体* 子物体 = nullptr;
		块 = f_ob_递归加载物体(&子物体, 块, ctx);

		f_ob_add子物体(ob[0], 子物体);
	}
	return 块;
}

static void f_ob_递归保存物体2(const S_物体* ob, S_UI8Array* 块) {
	
	f_文件块_写数据块(块, ob->m_Type);

	f_包宽字符串(块, ob->m_Name);

	f_文件块_写数据块(块, ob->m_变换.position);
	f_文件块_写数据块(块, ob->m_变换.rotation);
	f_文件块_写数据块(块, ob->m_变换.scale);

	f_an_Save通道(ob->m_位置, 块);
	f_an_Save通道(ob->m_旋转, 块);
	f_an_Save通道(ob->m_缩放, 块);

	f_文件块_写数据块(块, ob->m_视口显示模式);

	switch (ob->m_Type) {
		case E_物体类型::t_骨骼: {
			auto* 骨骼 = f_ob_from骨骼(ob);

			bool IK物体 = 骨骼->m_IK;
			f_文件块_写数据块(块, IK物体);
			if (IK物体) {
				f_ob_递归保存物体2(骨骼->m_IK->m_末端坐标, 块);
			}
			break;
		}
		default:
			break;
	}
	

	uint64 count = ob->m_子物体.size();
	f_文件块_写数据块(块, count);
	for (auto& e : ob->m_子物体) {
		f_ob_递归保存物体2(static_cast<S_物体*>(e), 块);
	}
}


const uint8* f_ob_递归加载物体(S_OBArray* obs, const uint8* 块, S_设备环境& ctx) {
	uint64 count = 0;
	块 = f_文件块_读数据块(块, count);

	f_core_array_resize((S_Array*)obs, count);
	for (uint32 i = 0; i < count; ++i) {
		块 = f_ob_递归加载物体(&obs->ptr_userData[i], 块, ctx);
	}
	return 块;
}

void f_ob_递归保存物体(const S_OBArray* obs, S_UI8Array* 块) {
	f_文件块_写数据块(块, obs->count);

	for (uint32 i = 0; i < obs->count; ++i) {
		
		S_OBArray buf;
		buf.ptr_userData = (S_物体**)(obs->ptr_userData[i]->m_子物体.data());
		buf.count = obs->ptr_userData[i]->m_子物体.size();

		f_ob_递归保存物体2(obs->ptr_userData[i], 块);
	}
}


static void f_递归复制物体属性(S_物体* d_ob, S_物体* s_ob) {
	d_ob->m_变换 = s_ob->m_变换;

	switch (d_ob->m_Type) {
		case E_物体类型::t_骨骼: {
			auto* d骨骼 = f_ob_from骨骼(d_ob);
			auto* s骨骼 = f_ob_from骨骼(s_ob);

			if (d骨骼->m_IK && d骨骼->m_IK->m_末端坐标) {
				d骨骼->m_IK->m_末端坐标->m_变换 = s骨骼->m_IK->m_末端坐标->m_变换;
			}
			break;
		}
		default:
			break;
	}

	uint64 count = d_ob->m_子物体.size();
	for (uint32 i = 0; i < count; ++i) {
		f_递归复制物体属性(static_cast<S_物体*>(d_ob->m_子物体[i]), static_cast<S_物体*>(s_ob->m_子物体[i]));
	}
}

void f_ob_复制物体属性(S_OBArray* d_ob, const S_OBArray* s_ob) {
	if(d_ob->count != s_ob->count) return;

	for (uint32 i = 0; i < d_ob->count; ++i) {
		f_递归复制物体属性(d_ob->ptr_userData[i], s_ob->ptr_userData[i]);
	}
}




void f_ob_Load多物体(S_OBArray* objs, FILE* f, S_设备环境& ctx, bool 数据) {
	uint32 num;
	fread(&num, sizeof(uint32), 1, f);
	f_core_array_resize((S_Array*)objs, num);
	
	for (uint32 i = 0; i < num; ++i) {
		S_物体* ob = new S_物体(E_物体类型::t_空);
		f_ob_Load物体(ob, f);
		f_ob_分配变换矩阵(ob, ctx);
		objs->ptr_userData[i] = ob;


		switch (objs->ptr_userData[i]->m_Type) {
		case E_物体类型::t_多边形:
			objs->ptr_userData[i]->m_UserData = f_surface_多边形加载(f);
			break;
		case E_物体类型::t_网格物体: {
			int32 数据槽数量 = 0;
			fread(&数据槽数量, sizeof(uint32), 1, f);

			f_ob_set数据槽数量(ob, 数据槽数量);
			for (uint32 j = 0; j < 数据槽数量; ++j) {
				auto* mesh = f_ob_getMesh(objs->ptr_userData[i], j);
			}
			break;
		}
		default:
			break;
		}
	}
}

void f_ob_Save多物体(const S_OBArray* objs, FILE* f, bool 数据) {
	fwrite(&objs->count, sizeof(uint32), 1, f);

	for (uint32 i = 0; i < objs->count; ++i) {
		f_ob_Save物体(objs->ptr_userData[i], f);


		switch (objs->ptr_userData[i]->m_Type) {
		case E_物体类型::t_多边形:
			f_surface_多边形保存(f, (S_多边形*)objs->ptr_userData[i]->m_UserData);
			break;
		case E_物体类型::t_网格物体: {
			//fwrite(&(mesh->m_是否链接), sizeof(bool), 1, f);
			//if(mesh->m_是否链接) f_save网格(f, mesh);

			int32 num = objs->ptr_userData[i]->m_DataNum;
			if (数据 && num) {
				fwrite(&num, sizeof(int32), 1, f);

				for (uint32 j = 0; j < num; ++j) {
					auto* mesh = f_ob_getMesh(objs->ptr_userData[i], j);
				}
			}
			else {
				num = 0;
				fwrite(&num, sizeof(int32), 1, f);
			}
			break;
		}

		default:
			break;
		}
	}
}

//const uint8* f_ob_Load模型(S_OBArray* obs, const uint8* 块, S_设备环境& ctx, bool 数据, fp_创建物体几何数据 模型创建回调) {
//
//}
//
//S_文件块 f_ob_Save模型(const S_OBArray* obs, S_UI8Array* 块, bool 数据, bool 压缩) {
//	//auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_模型物体, S_引擎配置::g_文件版本号);
//
//}


void f_load物体(FILE* f, S_物体* obj) {
	obj->m_Name = f_file_读取字符串(f);
	
	auto mat = f_创建BL右手转GL右手坐标系();

	auto matR = f_构建旋转矩阵(90.0, E_轴向::e_X);
	auto matRA = f_构建旋转矩阵(-90.0, E_轴向::e_X);
	auto matS = f_构建缩放矩阵(vec3{ 1.0, -1.0, 1.0 });
	mat = matS * matR;

	std::vector<vec3> 变换(3);
	f_读取文件(f, &变换);
	变换[1].x = -变换[1].x;
	变换[1].y = -变换[1].y;
	变换[1].z = -变换[1].z;
	
	obj->m_变换.position = 变换[0];
	obj->m_变换.rotation = 变换[1];
	obj->m_变换.scale = 变换[2];

	switch (obj->m_Type) {
	case E_物体类型::t_网格物体:
	case E_物体类型::t_多边形:
		f_load网格(f, dynamic_cast<S_模型*>(obj)->m_网格, DEF_Vert预设_vn);
		break;
	default:
		break;
	}
	
}

void f_save物体(FILE* f, S_物体* obj) {
	f_file_保存字符串(f, obj->m_Name);
	

	std::vector<vec3> 变换;
	变换.push_back(obj->m_变换.position);
	变换.push_back(obj->m_变换.rotation);
	变换.push_back(obj->m_变换.scale);
	f_写入文件(f, 变换);

	switch (obj->m_Type) {
	case E_物体类型::t_网格物体:
	case E_物体类型::t_多边形:
		f_save网格(f, dynamic_cast<S_模型*>(obj)->m_网格);
		break;
	default:
		break;
	}
}

std::vector<S_物体*> f_load多物体(FILE* f, S_设备环境 ctx) {
	uint32 num = 0;
	fread(&num, sizeof(uint32), 1, f);
	
	std::vector<S_物体*> data(num);
	if (!num) data;

	for (uint32 i = 0; i < num; ++i) {
		uint32 type = 0;
		file_单数值读取(f, type);

		data[i] = f_ob_创建(E_物体类型(type), 0, ctx);
		f_load物体(f, data[i]);
		if (ctx.m_Type == E_绘图API::E_Vulkan) {

		}
		else {
			
		}
		
	}
	
	return data;
}

void f_save多物体(FILE* f, const std::vector<S_物体*>& objs) {
	uint32 num = uint32(objs.size());
	auto* obj = objs.data();
	for (uint32 i = 0; i < num; ++i) {
		file_单数值保存(f, obj[i]->m_Type);

		f_save物体(f, obj[i]);
	}

}

std::vector<S_物体*> f_ob_loadFBX(const std::string& path, float32 预缩放, S_设备环境& ctx) {
	std::vector<S_物体*> objs;
	f_Ex加载FBX模型(objs, path, 预缩放, ctx);
	return objs;
}

std::vector<S_物体*> f_ob_loadOBJ(const std::string& path, S_设备环境 ctx, std::vector<S_纹理添加列队>& 纹理加载列队) {
	std::vector<S_物体*> objs;
	//f_Ex加载OBJ模型(ob, path, ctx, 纹理加载列队);
	return objs;
}

void f_ob_load(S_物体* ob, const S_Props& path, const S_Props& 类型后缀, const S_Props& 平滑法线, S_设备环境& ctx) {
	if(ob && (ob->m_Type != E_物体类型::t_网格物体 && ob->m_Type != E_物体类型::t_多边形)) return;

	
	auto 临时路径 = f_prop_LineStr(path);
	auto 文件路径 = f_file_补充文件路径后缀(临时路径, u"." + f_prop_enumName(类型后缀));

	auto 后缀名称 = f_file_get文件名后缀(文件路径);
	
	if (u".fbx" == 后缀名称) {
		//f_Ex加载FBX模型(objs, path, ctx);
	}
	else if (u".obj" == 后缀名称) {
		std::vector<S_纹理添加列队> 纹理加载列队;
		f_Ex加载OBJ模型(ob, f_str_u16_to_u8(文件路径), ctx, 纹理加载列队);
	}
	else if (u".stl" == 后缀名称) {
		//f_Ex加载OBJ模型(ob, 文件路径, ctx);
	}


	//if (".FBX" == 后缀名称 || ".fbx" == 后缀名称) {
	//	//f_Ex加载FBX模型(objs, path, ctx);
	//}
	//else if (".OBJ" == 后缀名称 || ".obj" == 后缀名称) {
	//	f_Ex加载OBJ模型(ob, 文件路径, ctx);
	//	std::cout<<"加载模型:"<< 文件路径<<" - 完成"<<std::endl;
	//}
}

void f_ob_Save(S_物体* ob, const S_Props& path, const S_Props& 类型后缀, const S_Props& 平滑法线) {
	//if (ob && (ob->m_Type != E_物体类型::t_网格 && ob->m_Type != E_物体类型::t_多边形)) return;

	auto 文件路径 = f_prop_LineStr(path);
	auto 后缀 = f_prop_enumName(类型后缀);

	f_ob_Save(ob, 文件路径, 后缀, f_prop_Bool(平滑法线));
}

std::u16string f_ob_Save(S_物体* ob, const std::u16string& path, const std::u16string& 后缀名称, bool 平滑法线, fp_坐标转换 fn) {
	if (ob && (ob->m_Type != E_物体类型::t_网格物体 && ob->m_Type != E_物体类型::t_多边形)) return u"";

	auto 文件路径 = f_file_补充文件路径后缀(path, u"." + 后缀名称);
	auto 后缀 = f_file_get文件名后缀(文件路径);

	if (u".fbx" == 后缀) {
		//f_Ex加载FBX模型(objs, 文件路径, ctx);
	}
	else if (u".obj" == 后缀) {
		//f_Ex加载OBJ模型(ob, 文件路径, ctx);
		//std::cout << "加载模型:" << 文件路径 << " - 完成" << std::endl;
	}
	else if (u".stl" == 后缀) {
		f_Ex保存STL模型(ob, f_str_u16_to_u8(文件路径), fn);
	}

	return 文件路径;
}













vec3 f_obj_get方向(S_物体* obj, E_轴向 轴向) {
	C_Mat44 mat = C_Mat44::kIdentity;

	auto rx = f_构建旋转矩阵(obj->m_变换.rotation.x, E_轴向::e_X);
	auto ry = f_构建旋转矩阵(obj->m_变换.rotation.y, E_轴向::e_Y);
	auto rz = f_构建旋转矩阵(obj->m_变换.rotation.z, E_轴向::e_Z);

	mat *= rz;
	mat *= ry;
	mat *= rx;

	mat = f_逆矩阵(mat);


	vec3 dir;
	switch (轴向) {
	case E_轴向::e_X:
		dir = mat * vec3{ 1.0f, 0.0f, 0.0f };
	case E_轴向::e_Y:
		dir = mat * vec3{ 0.0f, 1.0f, 0.0f };
	case E_轴向::e_Z:
		dir = mat * vec3{ 0.0f, 0.0f, 1.0f };
	default:
		break;
	}

	return vec_normalize2(dir);
}

vec3 f_ob_get中心(const std::vector<S_物体*>& obs, bool 包括子对象) {
	vec3 中心坐标 = {};
	uint32 num = 0;
	
	num += obs.size();
	for (auto& ob : obs) {
		if (包括子对象) {
			num += f_ob_get中心和(ob, 中心坐标);
		}
		else {
			中心坐标 += f_ob_get世界中心(ob, ob->m_网格拾取元素);
			
		}
	}

	return 中心坐标 / DEF_Max(num, 1);
}

void f_ob_增量移动(S_物体* obj, vec3 距离) {
	switch (obj->m_Type) {
	case E_物体类型::t_摄像机: {
		auto* came = dynamic_cast<S_摄像机*>(obj);
		//vec_add(&came->f_get视点偏移(), 距离);
		//came->m_isUpdate = true;
	}
		
		break;
	case E_物体类型::t_网格物体:

		break;
	default:
		break;
	}
}

void f_ob_set缩放(S_物体* obj, const vec3& 缩放) {
	obj->f_set缩放(缩放, obj->m_实例ID);
}




static vec3		g视点偏移 = {};
//static vec3		g视点平面偏移 = {};

float32 f_camera_get相机到视点距离(const S_摄像机* camera) {
	return fabs(camera->m_视距);
}

vec3 f_camera_get视线向量(const S_摄像机& camera) {
	return f_mat44_Invert(f_camera_计算旋转矩阵(camera, false)) * vec3{ 0, 0, DEF_ForwardDir };
}

vec3 f_camera_计算摄像机以角度缩放大小(S_摄像机* camera) {
	vec3 scale = { 1, 1.0f / camera->m_宽高比, float32(tan(M_角度转弧度(180 - camera->m_视角) * 0.5)) };
	return scale;
}

vec3 f_camera_get眼睛位置(const S_摄像机& camera) {
	return f_mat44_Invert(f_camera_计算变换矩阵(camera)) * vec3 { 0, 0, 0 };
}

vec3 f_camera_get视点位置(const S_摄像机& camera) {
	return camera.m_视点;
}

vec3 f_camera_get原点位置(const S_摄像机& camera) {
	vec3 原点 = f_camera_计算旋转矩阵(camera, false) * camera.m_视点偏移 + camera.m_视点;
	return -原点;
}

void f_camera_set摄像机视点位置(S_摄像机& camera, vec3 pos) {
	camera.m_isUpdate = true;
	camera.m_视点 = pos;
	camera.f_set视点偏移({});
}

void f_camera_set摄像机视点移动到偏移点(S_摄像机& camera) {
	camera.m_isUpdate = true;
	camera.f_set视点偏移({});
	return;
}

void f_camera_set偏移视点(S_摄像机& camera, const vec3& pos) {
	vec3 眼睛 = f_camera_get眼睛位置(camera);
	vec3 视线 = f_camera_get视线向量(camera);

	
	vec4 plane = f_graph_坐标构建平面(pos, -视线);
	float32 视线距离 = f_graph_点到平面距离(眼睛, plane);

	vec3 视点 = 眼睛 + (视线 * 视线距离 * DEF_ForwardDir);
	vec3 projCoordB = (视点 - pos);
	
	vec4 planeT = f_graph_坐标构建平面({}, 视线);
	vec2 projCoordA = f_graph_plane_PlaneCoord(projCoordB, planeT, {0,1,0});


	if (camera.m_投影模式 == E_投影模式::e_透视) {
		camera.m_视距 = 视线距离;
	}
	else {
		camera.m_视距;
	}

	camera.m_视点 = projCoordB - 视点;
	camera.m_视点偏移 = _Vec3(-projCoordA, 0);
	camera.m_isUpdate = true;
}

void f_camera_set旋转距离(S_摄像机& camera, const vec3& rot, float32 dis) {
	camera.m_变换.rotation = rot;
	camera.m_视距 = dis;
}

void f_camera_set旋转限制(S_摄像机& camera, const vec3 最小, const vec3 最大, bool 限制X轴, bool 限制Y轴, bool 限制Z轴) {
	camera.m_最小旋转限制 = 最小;
	camera.m_最大旋转限制 = 最大;

	camera.m_旋转限制[0] = 限制X轴;
	camera.m_旋转限制[1] = 限制Y轴;
	camera.m_旋转限制[2] = 限制Z轴;
}

vec3 f_camera_get相机视线平移方向(const S_摄像机& camera, vec3& H, vec3& V) {
	auto rx = RotationMatrix(M_角度转弧度(camera.m_变换.rotation.x), { 1.0f,0.0f,0.0f });
	auto ry = RotationMatrix(M_角度转弧度(camera.m_变换.rotation.y), { 0.0f,1.0f,0.0f });
	auto sel = ScaleMatrix({ camera.m_缩放.x, camera.m_缩放.y, camera.m_缩放.z });

	auto mat = f_逆矩阵((rx * ry) * sel);
	H = vec_normalize2(mat * vec3{ 1, 0, 0 });
	V = vec_normalize2(mat * vec3{ 0, 1, 0 });

	return H + V;
}

void f_camera_set转盘旋转(S_摄像机& camera, const vec3& rot) {
	camera.f_set累加旋转(-rot.x * 0.2, -rot.y * 0.2, rot.z);
	//camera->f_set累加旋转(-rot.y * 0.2, rot.x * 0.2, rot.z);

	if (camera.m_旋转限制[0]) {
		if (camera.m_变换.rotation.x < camera.m_最小旋转限制.x) {
			camera.m_变换.rotation.x = camera.m_最小旋转限制.x;
		}
		if (camera.m_变换.rotation.x > camera.m_最大旋转限制.x) {
			camera.m_变换.rotation.x = camera.m_最大旋转限制.x;
		}
	}
	if (camera.m_旋转限制[1]) {
		if (camera.m_变换.rotation.y < camera.m_最小旋转限制.y) {
			camera.m_变换.rotation.y = camera.m_最小旋转限制.y;
		}
		if (camera.m_变换.rotation.y > camera.m_最大旋转限制.y) {
			camera.m_变换.rotation.y = camera.m_最大旋转限制.y;
		}
	}
	if (camera.m_旋转限制[2]) {
		if (camera.m_变换.rotation.z < camera.m_最小旋转限制.z) {
			camera.m_变换.rotation.z = camera.m_最小旋转限制.z;
		}
		if (camera.m_变换.rotation.z > camera.m_最大旋转限制.z) {
			camera.m_变换.rotation.z = camera.m_最大旋转限制.z;
		}
	}
}

void f_camera_scal转盘距离(S_摄像机& camera, const float32 dis) {
	camera.f_set缩放(dis, dis, dis);
}




void f_camera_set转盘视点平移(S_摄像机& camera, vec2 move) {
	vec3 横向移动X = vec3{ 1, 0, 0 } * move.x;
	vec3 横向移动Y = vec3{ 0, 1, 0 } * move.y;
	
	camera.m_视点偏移 = g视点偏移 + 横向移动X + 横向移动Y;
	camera.m_isUpdate = true;
	return;
}

void f_camera_set转盘视点增量平移(S_摄像机& camera, vec2 move) {
	camera.m_视点偏移.x += move.x;
	camera.m_视点偏移.y += move.y;
	return;
}

void f_camera_开始相机变换(S_摄像机& camera, vec2 开始空间点坐标) {
	
	g视点偏移 = camera.m_视点偏移;

	if (g视点偏移.x > 1000000000) {
		g视点偏移.x = 1000000000;
	}
	if (g视点偏移.x < -1000000000) {
		g视点偏移.x = -1000000000;
	}
}

void f_camera_结束相机变换() {
	//g视点距离 = 0;
	g视点偏移 = {};
	//g视点 = {};
}





void f_ob_创建天空网格(S_设备环境& ctx, S_物体* ob, uint32 槽) {
	//S_物体* ob = f_ob_创建(ctx, E_物体类型::t_网格物体);
	//S_Mesh* me = f_surface_创建网格对象(nullptr, ctx, ctx.m_支持光追, E_网格数据枚举::e_Mesh_Vulkan);
	S_Mesh* me = f_ob_getMesh(ob, 槽);

	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	f_graph_构建球体(128, 64, 1, 顶点, 法线, UV, 索引);

	std::vector<S_VNT1> vnData;
	f_surface_数组合并(vnData, 顶点, 法线, UV);
	f_mesh_fill顶点数据(me, vnData);
	f_me_fill索引(me, 索引);

	f_mesh_计算包围盒(me);
	f_ob_set材质(ob, f_material_创建天空材质(ctx), 槽);
}

static void f_区域光物体变换更新(S_物体* ob, Mat44f* 矩阵, const Mat44f* 父级变换) {
	Mat44f mat = f_mat44_构建XYZ变换矩阵({ ob->m_变换.position, ob->m_变换.rotation, {1,1,1} });
	(*矩阵) = (*父级变换) * mat;

	auto me = f_ob_getMesh(ob, 0);
	f_bm_at<S_MeshTranformProp>(me->m_网格元素变换属性).m_Scale = 15;
}

S_物体* f_ob_创建区域光(S_设备环境& ctx) {
	S_物体* ob = f_ob_创建(ctx, E_物体类型::t_灯光);
	ob->m_视口显示模式 = 1 | 2 | 4 | 8;
	ob->m_视口显示模式 |= ob->m_视口显示模式 << 16;
	ob->m_颜色 = { 2,2,2,255 };
	ob->m_Name = u"区域光";
	ob->mf_变换回调更新 = f_区域光物体变换更新;
	

	f_ob_set数据槽数量(ob, 1);
	f_ob_set附属类型(ob, E_物体类型::t_灯光);

	f_buf_getGlobal().m_方形区域光物体网格->m_显示 = false;
	auto me = f_surface_创建实例(f_buf_getGlobal().m_方形区域光物体网格, true, true, true, true, true, true);
	me->m_显示 = false;

	
	
	f_ob_set数据(ob, me, 0);
	f_ob_set线宽(ob, 1.0, 0);
	f_mesh_set绘制内存属性(f_ob_getMesh(ob, 0), {});

	auto* 灯光材质 = f_material_创建PBR材质(ctx);
	f_ob_set材质(ob, 灯光材质);

	S_MeshTranformProp& 发光区变换属性 = f_buf_网格元素变换属性_at(me->m_网格元素变换属性, ob->m_实例ID);
	发光区变换属性.m_Scale = 0.1;

	return ob;
}

void f_ob_创建U型桶(S_设备环境& ctx, S_物体* ob, uint32 槽, float32 圆角比例) {
	auto poly = f_surface_创建多边形();

	uint32 细分 = 64;

	std::vector<vec2> 圆(细分);
	f_graph_计算圆坐标XZ(_Vec2(0), 1, 细分, 圆.data());

	S_Vec3Array* vert = (S_Vec3Array*)f_core_array_new_type(细分, E_值类型::e_Type_Vec3_1D);
	S_Vec3Array* new_vert = (S_Vec3Array*)f_core_array_new_type(细分, E_值类型::e_Type_Vec3_1D);
	for (uint32 i = 0; i < 细分; ++i) {
		vert->ptr_userData[i] = _Vec3(圆[i].x, 0, 圆[i].y);
	}

	uvec2 边顶点A = f_surface_添加多边形顶点(poly, vert, nullptr);
	auto* 边A = f_surface_添加多边形边(poly, 边顶点A, E_线绘制模式::e_线_闭合);
	f_poly_构建面(poly, 边A);


	{
		for (uint32 x = 0; x < 细分; ++x) {
			vec3 v = vert->ptr_userData[x];

			v.x += v.x * 圆角比例;
			v.z += v.z * 圆角比例;
			v.y += 圆角比例 * 3;

			new_vert->ptr_userData[x] = v;
		}
		auto 边顶点B = f_surface_添加多边形顶点(poly, new_vert, nullptr);
		边A = f_surface_添加多边形边(poly, 边顶点B, E_线绘制模式::e_线_闭合);
	}



	for (uint32 i = 0; i < 细分; ++i) {
		f_core_array_copy((S_Array*)new_vert, (S_Array*)vert);

		float a = M_角度转弧度((i+1) * (90.0f / 细分));

		for (uint32 x = 0; x < 细分; ++x) {
			vec3 v = vert->ptr_userData[x];

			v.x += v.x * cos(a) * 圆角比例;
			v.z += v.z * cos(a) * 圆角比例;
			v.y += 圆角比例 - sin(a) * 圆角比例;

			new_vert->ptr_userData[x] = v;
		}

		auto 边顶点B = f_surface_添加多边形顶点(poly, new_vert, nullptr);
		auto* 边B = f_surface_添加多边形边(poly, 边顶点B, E_线绘制模式::e_线_闭合);

		f_surface_多边形桥接(poly, *边A, *边B);
		边A = 边B;
	}
	

	S_Mesh* me = f_ob_getMesh(ob, 槽);
	uint32 num = poly->m_顶点.size();
	std::vector<S_VNT1> 面顶点(num);

	for (uint32 i = 0; i < num; ++i) {
		面顶点[i].vert = poly->m_顶点[i];
		面顶点[i].normal = {0,1,0};
		面顶点[i].UV = {};
	}

	f_mesh_fill顶点数据(me, 面顶点);
	f_mesh_多边形三角化(me, poly);
	f_mesh_计算包围盒(me);

	f_surface_销毁多边形(poly);

	f_surface_计算面平滑法线(me);
	f_mesh_set绘制内存属性(me, {});
}





void f_ob_set域(S_物体* Obj, S_DomProp& 域绘制参数, uint8 loc) {
	//if (Obj->m_GPU参数布局[loc].m_参数数量 >= 3) {
	//	S_DomProp 绘制参数;
	//	f_buf_fill板载缓存<S_DomProp>(Obj->m_GPU参数布局[loc].m_参数槽[2], &域绘制参数, 1, E_板载缓存类型::e_UBO);
	//}
}







void f_fromMesh创建体素(S_Mesh* srcMesh, const Mat44f& mat, float32 间距, std::vector<vec3>& vert) {
	//S_Mesh* mesh = f_mesh_创建体素提取网格(srcMesh);
	auto 包围盒 = f_ob_get包围盒(mat, *srcMesh->m_Bound);
	vec3 移动 = -(包围盒.pos - (包围盒.size * 0.5));

	vec3 meshLower = {};
	//vec3 meshUpper = 包围盒.size;
	

	vec3 edges = 包围盒.size;
	float32 maxEdge = DEF_Max(DEF_Max(edges.x, edges.y), edges.z);
	//meshUpper = { maxEdge , maxEdge , maxEdge };
	edges += 间距;

	std::vector<vec3> 变换后顶点;
	//f_surface_变换顶点(srcMesh, mat, vec3{ 1 / maxEdge, 1 / maxEdge, 1 / maxEdge }, 移动, 变换后顶点);
	//f_surface_变换顶点(srcMesh, mat, vec3{ 1,1,1 } / edges, 移动, 变换后顶点);
	f_surface_变换顶点(srcMesh, mat, vec3{1,1,1}, 移动, 变换后顶点);


	
	float 边缘间距 = 间距 * (1.0f - 1e-4f) * 0.5;

	//确保每个方向上至少有一个粒子
	int32 dx, dy, dz;
	dx = 间距 > edges.x ? 1 : int(edges.x / 间距);
	dy = 间距 > edges.y ? 1 : int(edges.y / 间距);
	dz = 间距 > edges.z ? 1 : int(edges.z / 间距);

	
	//通过两个体素扩展边界以确保在边缘进行足够的采样
	meshLower -= 边缘间距;
	//meshLower -= edges * 0.5;
	//meshUpper += 边缘间距;

	//vec3 meshOffset;
	//meshOffset.x = 0.5f * (间距 - (edges.x - (dx - 1) * 间距));
	//meshOffset.y = 0.5f * (间距 - (edges.y - (dy - 1) * 间距));
	//meshOffset.z = 0.5f * (间距 - (edges.z - (dz - 1) * 间距));
	//meshLower -= meshOffset;

	//std::vector<Point3>& 顶点 = *((std::vector<Point3>*)&变换后顶点);
	auto 索引 = srcMesh->f_map索引();

	uint64 体素数量 = dx * dy * dz;
	std::vector<uint8> voxels(体素数量);

	
	f_Voxelize遮罩(
		变换后顶点.data(),
		变换后顶点.size(),
		(uint32*)(索引.point),
		索引.count,
		dx, dy, dz,
		voxels.data(),
		meshLower,
		meshLower + vec3{dx * 间距, dy * 间距, dz * 间距}
	);


	meshLower += f_mat44_getMove(mat) - 包围盒.size * 0.5;

	//meshLower = 包围盒.size * 0.5;
	vert.reserve(体素数量);
	for (int z = 0; z < dz; ++z) {
		int32 层ID = (z * dx * dy);

		for (int y = 0; y < dy; ++y) {
			for (int x = 0; x < dx; ++x) {
				const int index = 层ID + (y * dx) + x;

				// if voxel is marked as occupied the add a particle
				if (voxels[index]) {
					vec3 point = _Vec3(x, y, z);
					point *= 间距;
					//point = mat * point;
					//point -= meshLower;
					point += meshLower + 边缘间距;
					point += f_random_单位向量() * 0.1 * 间距;
					vert.push_back(point);
				}
			}
		}
	}
}








//void f_ob_create骨骼虚拟体网格(S_设备环境& ctx, S_物体* 骨骼) {
//	vec2 size = { 1.0f, 0.1f };
//	DEF_3Fs V;
//	DEF_3Fs N;
//	DEF_Is I;
//	DEF_2Fs uv;
//
//	auto* 骨骼mesh = f_surface_创建实例(S_Mesh::g_骨头锥形, true, true, true, false);
//	骨骼->f_setData(骨骼mesh, 0);
//
//	f_graph_构建骨骼锥体(size, V, N, I);
//	f_surface_fill顶点数据(骨骼mesh, V);
//	f_surface_fill索引数据(骨骼mesh, I);
//	f_surface_计算包围盒(骨骼mesh);
//
//	骨骼mesh->m_线宽 = 3.0;
//	骨骼mesh->m_深度控制 = { 0.0001f, 0.0f };
//
//	
//	
//	auto* 骨节mesh = f_surface_创建实例(S_Mesh::g_骨节圆形, true, true, true, false);
//	f_graph_构建球体(32, 16, size.y*0.5, V, N, uv, I);
//	f_surface_fill顶点数据(骨节mesh, V);
//	f_surface_fill索引数据(骨节mesh, I);
//	f_surface_计算包围盒(骨节mesh);
//
//	骨节mesh->m_线宽 = 3.0;
//	骨节mesh->m_深度控制 = { 0.0001f, 0.0f };
//
//
//	f_mesh_set绘制属性(骨骼mesh, {});
//	f_mesh_set绘制属性(骨节mesh, {});
//
//
//	f_ob_set数据槽数量(骨骼, 2);
//	f_ob_set数据(骨骼, 骨骼mesh, E_物体网格元素类型::e_MT_轮廓);
//	f_ob_set材质(骨骼, f_NodeCtx_get基本光照面轮廓材质(), E_物体网格元素类型::e_MT_轮廓);
//	f_ob_set线宽(骨骼, 2.0, 0);
//	f_ob_set数据(骨骼, 骨骼mesh, E_物体网格元素类型::e_MT_面);
//	f_ob_set材质(骨骼, f_NodeCtx_get基本光照面轮廓材质(), E_物体网格元素类型::e_MT_面);
//	f_ob_set线宽(骨骼, 2.0, 1);
//}

/*void f_ob_重置顶点数量(S_物体* Obj, uint32 num) {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	f_buf_gresize(m_顶点, num);
	f_buf_resize(((S_VKMesh板载缓存*)mesh->m_网格)->m_顶点, num, E_板载缓存类型::e_VBO);
}*/


//vec3 f_get相机变换后位置(S_摄像机* camera) {
//	//auto 逆矩阵 = f_求逆矩阵(camera->m_相机位置矩阵);
//	//return 逆矩阵 * vec3{ 0.0f, 0.0f, camera->m_视点距离 };
//	return f_逆矩阵(*(Mat44*)&camera->m_相机位置矩阵) * vec3{ 0.0f, 0.0f, camera->m_视点距离 * DEF_ForwardDir } - camera->f_get视点偏移();
//}


//Mat44f f_ob_get实例变换矩阵(S_物体* Ob, uint32 ID) {
//	if (ID < Ob->m_变换矩阵.m_Mem.m_大小) f_buf_Mat44_at(Ob->m_变换矩阵, ID);
//	return f_buf_Mat44_at(Ob->m_变换矩阵, 0);
//}

/*void f_ob_创建实例Data(S_物体* Obj, void* data, uint8 loc) {
	switch (Obj->m_Type) {
	case E_物体类型::t_网格:
		if (Obj->m_几何体[loc] == nullptr) {
			//Obj->m_几何体[loc] = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
		}
		//f_surface_创建实例(Obj->m_几何体[loc], (S_Mesh*)data);
		break;
	}
}*/

Inline VkWriteDescriptorSetAccelerationStructureKHR* f_创建加速结构描述集(void** descriptor) {
	VkWriteDescriptorSetAccelerationStructureKHR* acc = (VkWriteDescriptorSetAccelerationStructureKHR*)descriptor[0];
	if (!acc) {
		acc = (VkWriteDescriptorSetAccelerationStructureKHR*)malloc(sizeof(VkWriteDescriptorSetAccelerationStructureKHR));

		(*acc) = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR };
		descriptor[0] = acc;
	}
	return acc;
}
Inline VkAccelerationStructureKHR* f_创建加速结构引用(VkWriteDescriptorSetAccelerationStructureKHR* acc, uint32 num) {
	VkAccelerationStructureKHR* data = nullptr;
	if (acc->accelerationStructureCount != num) {
		if (acc->pAccelerationStructures) {
			free((void*)acc->pAccelerationStructures);
		}

		data = (VkAccelerationStructureKHR*)malloc(sizeof(VkAccelerationStructureKHR) * num);
		acc->pAccelerationStructures = data;
		(*acc).accelerationStructureCount = num;
	}
	else {
		data = (VkAccelerationStructureKHR*)acc->pAccelerationStructures;
	}
	return data;
}


void f_ob_光追加速结构描述集(S_渲染世界* 世界) {
	VkWriteDescriptorSetAccelerationStructureKHR* acc = f_创建加速结构描述集(&世界->m_光追描述集);
	//uint32 num = 世界->m_层.size();
	uint32 num = 世界->m_物体指针.m_Mem.m_数量;
	auto* data = f_创建加速结构引用(acc, num);
	for (uint32 i = 0; i < num; ++i) {
		data[i] = (VkAccelerationStructureKHR)(f_buf_get加速结构(世界->m_层[i]->m_光追顶层加速结构));
	}
}

void f_ob_光追加速结构描述集(S_物体** ob, uint32 num, void** descriptor) {
	VkWriteDescriptorSetAccelerationStructureKHR* acc = (VkWriteDescriptorSetAccelerationStructureKHR*)(descriptor[0]);
	if (!acc) {
		acc = (VkWriteDescriptorSetAccelerationStructureKHR*)malloc(sizeof(VkWriteDescriptorSetAccelerationStructureKHR));

		(*acc) = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR };
		descriptor[0] = acc;
	}

	VkAccelerationStructureKHR* data = nullptr;
	if (acc->accelerationStructureCount != num) {
		if (acc->pAccelerationStructures) {
			free((void*)acc->pAccelerationStructures);
		}

		data = (VkAccelerationStructureKHR*)malloc(sizeof(VkAccelerationStructureKHR) * num);
		acc->pAccelerationStructures = data;
		(*acc).accelerationStructureCount = num;
	}
	else {
		data = (VkAccelerationStructureKHR*)acc->pAccelerationStructures;
	}

	for (uint32 i = 0; i < num; ++i) {
		data[i] = (VkAccelerationStructureKHR)(f_buf_get加速结构(ob[i]->m_光追顶层加速结构));
	}
}

void f_ob_光追加速结构描述集(S_GPU内存块& 内存块, void** descriptor) {
	VkWriteDescriptorSetAccelerationStructureKHR* acc = f_创建加速结构描述集(descriptor);

	VkAccelerationStructureKHR* data = f_创建加速结构引用(acc, 1);
	if (acc, 内存块.m_Mem.m_数量) {
		data[0] = (VkAccelerationStructureKHR)(f_buf_get加速结构(内存块));
	}
	else {
		data[0] = (VkAccelerationStructureKHR)(f_buf_get加速结构(内存块.m_Buf));
	}
}

void f_ob_销毁光追加速结构描述集(void* descriptor) {
	if (descriptor) {
		VkWriteDescriptorSetAccelerationStructureKHR* acc = (VkWriteDescriptorSetAccelerationStructureKHR*)descriptor;

		free((void*)acc->pAccelerationStructures);
		free(descriptor);
	}
}

uint32 f_ob_get光追加速结构描述集数量(void* descriptor) {
	return ((VkWriteDescriptorSetAccelerationStructureKHR*)descriptor)->accelerationStructureCount;
}

